package test;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

public class MappingTool {

    public static String toJson(Object o) throws IOException {
        // 获取对象的类
        Class<?> clazz = getClz(o);

        // 初始化StringBuilder
        StringBuilder sb = new StringBuilder();
        sb.append("{"); // 添加 JSON 开始符

        // 遍历对象的所有字段
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true); // 确保可以访问私有字段
            Object value = getFieldValue(field, o);

            // 使用单引号包裹字段名和值，且使用空格分隔
            sb.append("'").append(field.getName()).append("':");

            if (value == null) {
                sb.append("null");
            } else if (field.getType().equals(String.class)) {
                sb.append("'").append(value.toString()).append("'");
            } else {
                sb.append(value.toString());
            }
            sb.append(", ");
        }

        if (sb.length() > 1) {
            sb.setLength(sb.length() - 2); // 移除最后一个逗号和空格
        }
        sb.append("}"); // 添加 JSON 结束符

        return sb.toString();
    }

    private static Class<?> getClz(Object o) {
        if (o == null)
            throw new IllegalArgumentException("不能对null对象进行操作");
        return o.getClass();
    }

    private static Object getFieldValue(Field field, Object o) throws IOException {
        try {
            return field.get(o);
        } catch (IllegalAccessException e) {
            throw new IOException("无法访问字段: " + field.getName(), e);
        }
    }

    @SuppressWarnings("unchecked")
    public static <T> T fromJson(HashMap<String, Object> map, Class<T> clazz) throws IOException {
        try {
            T instance = clazz.getDeclaredConstructor().newInstance();

            for (Map.Entry<String, Object> entry : map.entrySet()) {
                String key = entry.getKey();
                Object value = entry.getValue();

                Field field = clazz.getDeclaredField(key);
                field.setAccessible(true);

                if (field.getType().equals(String.class)) {
                    field.set(instance, value.toString());
                } else if (field.getType().equals(int.class) || field.getType().equals(Integer.class)) {
                    field.set(instance, Integer.parseInt(value.toString()));
                } else if (field.getType().equals(double.class) || field.getType().equals(Double.class)) {
                    field.set(instance, Double.parseDouble(value.toString()));
                } else if (field.getType().equals(boolean.class) || field.getType().equals(Boolean.class)) {
                    field.set(instance, Boolean.parseBoolean(value.toString()));
                } else {
                    field.set(instance, value);
                }
            }

            return instance;
        } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchFieldException e) {
            throw new IOException("无法将 JSON 转换为对象", e);
        }
    }

    public static void main(String[] args) {
        try {
            // 示例对象
            Person person = new Person();
            person.setName("Alice");
            person.setAge(30);

            // 对象转 JSON
            String json = toJson(person);
            System.out.println("JSON: " + json);

            // JSON 转对象
            HashMap<String, Object> map = new HashMap<>();
            map.put("name", "Bob");
            map.put("age", 25);

            Person newPerson = fromJson(map, Person.class);
            System.out.println("New Person Name: " + newPerson.getName());
            System.out.println("New Person Age: " + newPerson.getAge());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

class Person {
    private String name;
    private int age;

    // 无参构造方法
    public Person() {
    }

    // 带参数的构造方法
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // Getter 和 Setter 方法
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
